
package cn.devpt.dev.auth.filter;

import cn.devpt.dev.auth.entity.AuthUser;
import cn.devpt.dev.auth.service.LoginService;
import cn.devpt.dev.auth.service.impl.LoginServiceImpl;
import cn.devpt.dev.util.PtUtil;
import cn.devpt.dev.util.SpringUtil;
import org.apache.log4j.Logger;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;

/**
 * wxl 增加 vue支持
 *
 * @author jason
 */
// @WebFilter(filterName = "LoginFilter", urlPatterns = {"/*"})
public class LoginFilter implements Filter {


    private static final boolean debug = false;
    private static final Logger LOG = Logger.getLogger(LoginFilter.class.getName());

    // The filter configuration object we are associated with. If
    // this value is null, this filter instance is not currently
    // configured.
    private FilterConfig filterConfig = null;

    public LoginFilter() {
    }

    private void doBeforeProcessing(ServletRequest request, ServletResponse response)
            throws IOException, ServletException {
        if (debug) {
            log("LoginFilter:DoBeforeProcessing");
        }

        // Write code here to process the request and/or response before
        // the rest of the filter chain is invoked.
        // For example, a logging filter might log items on the request object,
        // such as the parameters.
        /*
         * for (Enumeration en = request.getParameterNames();
         * en.hasMoreElements(); ) { String name = (String)en.nextElement();
         * String values[] = request.getParameterValues(name); int n =
         * values.length; StringBuffer buf = new StringBuffer();
         * buf.append(name); buf.append("="); for(int i=0; i < n; i++) {
         * buf.append(values[i]); if (i < n-1) buf.append(","); }
         * log(buf.toString()); }
         */
    }

    private void doAfterProcessing(ServletRequest request, ServletResponse response)
            throws IOException, ServletException {
        if (debug) {
            log("LoginFilter:DoAfterProcessing");
        }

        // Write code here to process the request and/or response after
        // the rest of the filter chain is invoked.
        // For example, a logging filter might log the attributes on the
        // request object after the request has been processed.
        /*
         * for (Enumeration en = request.getAttributeNames();
         * en.hasMoreElements(); ) { String name = (String)en.nextElement();
         * Object value = request.getAttribute(name); log("attribute: " + name +
         * "=" + value.toString());
         *
         * }
         */
        // For example, a filter might append something to the response.
        /*
         * PrintWriter respOut = new PrintWriter(response.getWriter()); respOut.
         * println("<P><B>This has been appended by an intrusive filter.</B>");
         */
    }

    private String parsePermission(HttpServletRequest request) {
        if ("".equals(request.getContextPath())) {
            return request.getRequestURI().substring(1).replace("/", ":");
        } else {
            return request.getRequestURI().replace(request.getContextPath() + "/", "").replace("/", ":");
        }
    }

    /**
     * @param request  The servlet request we are processing
     * @param response The servlet response we are creating
     * @param chain    The filter chain we are processing
     * @throws IOException      if an input/output error occurs
     * @throws ServletException if a servlet error occurs
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        // log("doFilter() running...");
        if (debug) {
            log("LoginFilter:doFilter()");
        }

        doBeforeProcessing(request, response);
        HttpServletResponse hResponse = (HttpServletResponse) response;
        // 编码
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        Object obj = PtUtil.getCurUser();
        final HttpServletRequest hRequest = (HttpServletRequest) request;
        String ptTokenId = (String) hRequest.getHeader("ptTokenId");
        // 判断是否登录。wxl
        if (obj == null) {
            if (PtUtil.strNotNull(ptTokenId)) {
                LoginService loginService = SpringUtil.getBean(LoginServiceImpl.class);
                AuthUser user = loginService.loginByToken(ptTokenId);
                if (user == null) {
                    PrintWriter out = hResponse.getWriter();
                    out.println(-999);// 重新登录
                    return;
                }
            } else {
                hResponse.sendRedirect(request.getServletContext().getContextPath() + "/index.html");

            }
        }


        String title = hRequest.getHeader("hdTabTitle");

        // final String permission =
        // hRequest.getRequestURI().replace(hRequest.getContextPath() + "/",
        // "").replace("/", ":");
        final String permission = parsePermission(hRequest);
        String isAccessed = "1";
        // 对于jsp和html进行免检测。
        // if (!permission.contains(".jsp") && !permission.contains(".html") &&
        // !permission.contains("png") && !permission.contains("jpg") &&
        // !permission.contains("js")) {
        // // TODO 资源控制，将注解取消即可启动测试。
        // // 验证是否有访问权限。
        // LOG.info(permission);
        // //开启权限认证，将下列代码注释去掉
        // if (!SecurityUtils.getSubject().isPermitted(permission)) {
        // hResponse.getWriter().write("<html><head><meta
        // charset=\"UTF-8\"><title>warnning!</title></head><body><script>alert('no
        // permission！');</script></body></html>");
        // hResponse.setStatus(403);
        // hResponse.getWriter().close();
        //
        // isAccessed = "0";
        // }
        // }
        // 写日志。
        // LOG.info("处理日志时间=" + (System.currentTimeMillis() - st) + "ms");
        // if
        // (request.getServletContext().getInitParameter("accessLog").equals("true"))
        // {

        // if ("1".equals(loginfilterServices.get("ACCESS_LOG", "LOG"))) {
        // AuthUser user = (AuthUser)
        // SecurityUtils.getSubject().getSession().getAttribute(PrivilegeController.SESSION_USER);
        // AuthLogAccess ala = new AuthLogAccess();
        // if (title != null && !title.equals("")) {
        // ala.setFunction(URLDecoder.decode(title, "UTF-8"));
        // }
        // ala.setIp(user.getIp());
        // ala.setUserId(user.getUserId());
        // ala.setInsTimestamp(new Date());
        // ala.setUrlId(permission);
        // ala.setBrowser(hRequest.getHeader("User-Agent"));
        // loginfilterServices.edit(ala);
        // // ((AuthLogAccessFacade)
        // HdFacadeFactory.getFacade(Constants.EJB_URI,
        // AuthLogAccessFacade.class)).edit(ala);
        // // log.setIsAccessed(isAccessed);
        // // log.setMethod(hRequest.getMethod());
        // // 写访问日志。(利用线程池进行。)
        //// long st = System.currentTimeMillis();
        //// HdLogThreadPool.getInstance().execute(new Runnable() {
        //// @Override
        //// public void run() {
        // // AuthLogPK pk = new AuthLogPK();
        // // pk.setAuthUserId(user.getId());
        // // // 获得当前权限id。
        // // pk.setPermission(permission);
        // // pk.setInsTimestamp(new Date());
        // // log.setIp(hRequest.getRemoteAddr());
        // // log.setBrowser(hRequest.getHeader("User-Agent"));
        // // log.setAuthLogPK(pk);
        // // AuthLogFacade facade =
        // HdFacadeFactory.getFacade(Constants.EJB_URI, AuthLogFacade.class);
        // // facade.create(log);
        //// }
        //// });
        // }
        if (isAccessed.equals("0")) {
            return;
        }
        Throwable problem = null;
        try {
            chain.doFilter(request, response);
        } catch (Throwable t) {
            // If an exception is thrown somewhere down the filter chain,
            // we still want to execute our after processing, and then
            // rethrow the problem after that.
            problem = t;
            t.printStackTrace();
        }

        doAfterProcessing(request, response);

        // If there was a problem, we want to rethrow it if it is
        // a known type, otherwise log it.
        if (problem != null) {
            if (problem instanceof ServletException) {
                throw (ServletException) problem;
            }
            if (problem instanceof IOException) {
                throw (IOException) problem;
            }
            sendProcessingError(problem, response);
        }
    }

    /**
     * Return the filter configuration object for this filter.
     */
    public FilterConfig getFilterConfig() {
        return (this.filterConfig);
    }

    /**
     * Set the filter configuration object for this filter.
     *
     * @param filterConfig The filter configuration object
     */
    public void setFilterConfig(FilterConfig filterConfig) {
        this.filterConfig = filterConfig;
    }

    /**
     * Destroy method for this filter
     */
    public void destroy() {
    }

    /**
     * Init method for this filter
     */
    public void init(FilterConfig filterConfig) {
        this.filterConfig = filterConfig;
        if (filterConfig != null) {
            if (debug) {
                log("LoginFilter:Initializing filter");
            }
        }
    }

    /**
     * Return a String representation of this object.
     */
    @Override
    public String toString() {
        if (filterConfig == null) {
            return ("LoginFilter()");
        }
        StringBuffer sb = new StringBuffer("LoginFilter(");
        sb.append(filterConfig);
        sb.append(")");
        return (sb.toString());
    }

    private void sendProcessingError(Throwable t, ServletResponse response) {
        String stackTrace = getStackTrace(t);

        if (stackTrace != null && !stackTrace.equals("")) {
            try {
                response.setContentType("text/html");
                PrintStream ps = new PrintStream(response.getOutputStream());
                PrintWriter pw = new PrintWriter(ps);
                pw.print("<html>\n<head>\n<title>Error</title>\n</head>\n<body>\n"); // NOI18N

                // PENDING! Localize this for next official release
                pw.print("<h1>The resource did not process correctly</h1>\n<pre>\n");
                pw.print(stackTrace);
                pw.print("</pre></body>\n</html>"); // NOI18N
                pw.close();
                ps.close();
                response.getOutputStream().close();
            } catch (Exception ex) {
            }
        } else {
            try {
                PrintStream ps = new PrintStream(response.getOutputStream());
                t.printStackTrace(ps);
                ps.close();
                response.getOutputStream().close();
            } catch (Exception ex) {
            }
        }
    }

    public static String getStackTrace(Throwable t) {
        String stackTrace = null;
        try {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            t.printStackTrace(pw);
            pw.close();
            sw.close();
            stackTrace = sw.getBuffer().toString();
        } catch (Exception ex) {
        }
        return stackTrace;
    }

    public void log(String msg) {
        LOG.info(msg);
    }
}
